<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <title>JS打字小游戏</title>
    <style>
        body {
            padding: 0;
            margin: 0;
        }
        #gameStage {
            width: 100%;
            height: 1000px;
            background-color: aquamarine;

        }
        #score{
            position: fixed;
            right: 0;
            top:0;
            width: 200px;
            height:80px;
            line-height: 40px;
            background: rgba(250,10,10,0.7);
            z-index:2;
            color: #fff;
            font-size: 24px;
            text-align:center;
        }
    </style>
</head>
<body>
<div id="gameStage">
    <div id="score">
        <span>错误次数</span>
        <br/>
        <span id="def">0</span>
    </div>
</div>
<script>
    /**
     * 字母
     * @param id
     * @param alphabet
     * @param posX
     * @param posY
     * @param size
     * @constructor
     */
    function Word(id, alphabet, posX, posY, size) {
        //初始化数据
        this.id = id || '';
        this.alphabet = alphabet || 'a';
        this.posX = posX || 0;
        this.posY = posY || 0;
        this.size = size || 64;
        // 新建
        this.create = function () {
            var str = '<span class="word" id="alphabet-' + this.id + '">' + this.alphabet + '</span>';
            var gameStage = document.getElementById('gameStage');
            gameStage.innerHTML += str;
            var divNode = document.getElementById('alphabet-' + this.id);
            divNode.style.position = 'absolute';
            divNode.style.fontSize = this.size + 'px';
            divNode.style.left = this.posX + 'px';
            divNode.style.top = this.posY + 'px';
        };
        // 重置.
        this.reset = function () {
            var divNode = document.getElementById('alphabet-' + this.id);
            divNode.style.display = 'none';
            this.moveTo(0, 0);
        };
        // 移动到指定点
        this.moveTo = function (posX, posY) {
            this.posX = posX;
            this.posY = posY;
            var divNode = document.getElementById('alphabet-' + this.id);
            divNode.style.left = posX + 'px';
            divNode.style.top = posY + 'px';
        };
    }
    /**
     * 导演类
     */
    var director = {
        alphabets: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
            'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],

        nodes: new Array(),

        /**
         * 逐帧运行
         */
        runFrame: function () {

            //更新已经产生所有点的坐标
            for (var index in this.nodes) {
                var node = this.nodes[index];
                if (node) {
                    node.moveTo(node.posX, node.posY + 10);
                }
                if(node&&node.posY>window.innerHeight-50){
                    gameOver();                                                 //显示最终得分
                }
            }

            //随机产生字母
            var r = Math.floor(Math.random() * this.alphabets.length);
            var w = new Word(new Date().getTime(), this.alphabets[r]);

            w.create();
            this.nodes.push(w);

            var posX = Math.floor(Math.random() * window.innerWidth);
            if (posX < 50) {
                posX = 100;
            }
            if (posX >= window.innerWidth - 100) {
                posX = window.innerWidth - 100;                         //防止字母显示在屏幕外
            }
            w.moveTo(posX, 0);
        },

        /**
         * 开始游戏
         */
        start: function () {
            var _this = this;
            //标志位，判断是否找到
            //监听键盘事件
            document.onkeydown = function () {
                var flag = false;
                var alphabet = String.fromCharCode(event.keyCode); //获取键盘敲中的字母
                for (var i = 0, len = _this.nodes.length; i < len; i++) {
                    if(!_this.nodes[i]) {
                        continue;
                    }
                    if (alphabet === _this.nodes[i].alphabet) {
                        _this.nodes[i].reset();
                        scoreCounter.incScore();
                        _this.nodes[i] = null;
                        flag = true;
                    }
                    disScore.myFunction();
                }
                if(!flag) {
                    scoreCounter.decScore();
                    disScore.myFunction();
                    scoreCounter.errScore();
                }

            };
            //游戏主循环
            setInterval(function () {
                _this.runFrame();
            }, 400);
        }

    }

    /**
     * 计分器
     */
    var scoreCounter = {
        score : 0,
        errorScore : 0,
        incScore: function () {
            this.score++;
        },
        decScore: function () {
            this.score--;
        },
        getScore: function () {
            return this.score;
        },
        errScore:function () {
            this.errorScore++;
        },
        getErrorScore:function () {
            return this.errorScore;
        }
    };

    /**
     *显示实时得分
     **/
    var  disScore =
        {
            myFunction : function () {
                document.getElementById("def").innerHTML = scoreCounter.getErrorScore();         //显示错误次数
            }
        }

    /**
     *显示游戏结束提示
     **/

    function gameOver(){
        if(confirm("游戏结束你分数是："+scoreCounter.getScore()+"\n是否重新开始游戏？")){
            location.reload();
        }else{
            window.close();
        }
    }
    director.start();

</script>
</body>

</html>